package com.sea.base.permission

import android.os.Bundle
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import com.sea.base.ext.global.logE
import com.sea.base.ext.global.toastAndLogDebug
import com.sea.base.utils.ActivityStackManager

internal class PermissionFragment : Fragment() {
    companion object {
        private val TAG = PermissionFragment::class.java.name

        /**
         * 不允许连续多次请求权限，见Activity.requestPermissions().mHasCurrentPermissionsRequest
         * 并且连续请求系统会返回错乱结果
         * 所以全局只能有一个权限请求
         */
        private var requestingPermissions: Array<String>? = null

        /**
         * @param resultCallback isReqSuccess：是否请求发起成功
         */
        fun reqPermission(
            ui: com.sea.base.ui.IUIContext,
            reqPermissions: Array<String>,
            onCreateCallback: Fragment.() -> Unit,
            resultCallback: (isReqSuccess: Boolean, resultMap: Map<String, Boolean>) -> Unit,
        ) {
            if (requestingPermissions != null) {
                //如果有正在请求的权限，则遍历所有的Fragment确定是否真的正在请求
                val requestingFragments = ActivityStackManager.getNowActivityStack()
                    .mapNotNull { it as? FragmentActivity }
                    .flatMap { it.supportFragmentManager.fragments }
                    .mapNotNull { it as? PermissionFragment }
                    .mapNotNull { frag ->
                        if (frag.reqPermissions == null) {
                            frag.activity?.supportFragmentManager?.let { removeFrag(it) }
                            null
                        } else {
                            frag
                        }
                    }
                if (requestingFragments.isNotEmpty()) {
                    "连续多次请求了权限，旧：${requestingPermissions}，新：${reqPermissions}（已忽略）".toastAndLogDebug()
                    resultCallback.invoke(false, reqPermissions.associateWith { false })
                    return
                } else {
                    requestingPermissions = null
                }
            }
            //可能重建导致有空frag
            removeFrag(ui.currentFragmentManager)

            requestingPermissions = reqPermissions

            ui.currentFragmentManager
                .beginTransaction()
                .add(PermissionFragment().apply {
                    this.reqPermissions = reqPermissions
                    this.resultCallback = resultCallback
                    this.onCreateCallback = onCreateCallback
                }, TAG)
                .commitNowAllowingStateLoss()
        }

        private fun removeFrag(fm: FragmentManager) {
            try {
                val oldFrag = fm.findFragmentByTag(TAG) as? PermissionFragment
                if (oldFrag != null) {
                    fm.beginTransaction().remove(oldFrag).commitNowAllowingStateLoss()
                }
            } catch (e: Exception) {
                "ERROR: ${e.message}".logE(TAG)
            }
        }
    }

    private var reqPermissions: Array<String>? = null
    private var resultCallback: ((isReqSuccess: Boolean, resultMap: Map<String, Boolean>) -> Unit)? = null
    private var onCreateCallback: (PermissionFragment.() -> Unit)? = null

    private val startPermissionResult =
        registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {
            if (reqPermissions.contentEquals(requestingPermissions)) {
                requestingPermissions = null
            }
            callResultAndRelease(true, it)
            removeFrag(parentFragmentManager)
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        retainInstance = true //activity 异常重建时 ，fragment不重建

        onCreateCallback?.invoke(this)

        reqPermissions?.let {
            startPermissionResult.launch(it)
        } ?: let {
            callResultAndRelease(false, emptyMap())
            removeFrag(parentFragmentManager)
        }
    }

    override fun onDestroy() {
        if (reqPermissions.contentEquals(requestingPermissions)) {
            requestingPermissions = null
        }
        reqPermissions?.let { reqPermissions ->
            callResultAndRelease(false, reqPermissions.associateWith { false })
        }
        super.onDestroy()
    }

    private fun callResultAndRelease(isReqSuccess: Boolean, resultMap: Map<String, Boolean>) {
        resultCallback?.invoke(isReqSuccess, resultMap)

        reqPermissions = null
        resultCallback = null
        onCreateCallback = null
    }
}

